/*
 * @描述: 
 * @创建者: kilomChou
 * @Date: 2021-04-11 17:21:46
 * @最后编辑: kilomChou
 * @LastEditTime: 2021-05-15 11:31:05
 */
import { RandUtil } from "../../util/RandUtil";
import BaseAI, { IBaseAI } from "./BaseAI";
import Food from "../world/Food";
import { ICircle, Vec2 } from "../../core/vec2/Vec2";
import Vec2Operator from "../../core/vec2/Vec2Operator";
const [v2, v2op] = [Vec2, new Vec2Operator()];

export interface IAIEat extends IBaseAI {
    findDistance: number | [number, number]
    /** 食物数量少于多少就更新寻找组 (默认0.75)*/
    foodLessUpdate?: number | [number, number]
}

/** 智能进食 */
export default class AIEat extends BaseAI {

    constructor(obj: IAIEat) {
        super(obj)
        this._findDistance = this.toMinMax(obj.findDistance)
        this._foodLessUpdate = this.toMinMax(obj.foodLessUpdate || 0.75)
    }

    private _findDistance: number[]
    private _foodLessUpdate: number[]
    private _findDis!: number
    private _foodLess!: number
    private _foods!: Food[]
    private _foodMin!: number
    private _food!: Food

    getKey(): string { return "ai_eat" + this.snake.id }

    aiStart() {
        let head = this.head
        this._findDis = RandUtil.rand2(this._findDistance) * head.w + head.w
        this._foodLess = RandUtil.rand2(this._foodLessUpdate)
        this.updateFindFoods()
    }

    ai(dt: number): void {

        if (!this._foods || this._foods.length < this._foodMin) {
            this.updateFindFoods()
        }

        while (!this._food) {
            if (this._foods.length) {
                let food = this._foods.shift()
                if (food!.isLive) {
                    this._food = food!
                }
            } else {
                this._foods = null!
                break
            }

        }

        if (this._food) {
            if (this._food.isLive) {
                let head = this.head
                this.snake.toAng = v2.angTo(head, this._food);
            } else {
                this._food = null!
            }
        }

    }

    aiStop() {
        this._foods = this._food = null!
    }

    private updateFindFoods() {
        let head = this.snake.head
        let findCol = v2op.setObj(tmpCir).posAs(head).setR(this._findDis * 0.5);
        let chunks = this.world.getChunks(findCol.obj)
        this._foods = this.world.getFoods(chunks).sort((f1, f2) => {
            let d1 = findCol.dis(f1)
            let d2 = findCol.dis(f2)
            return d1 - d2
        })
        this._foodMin = this._foods.length * this._foodLess
    }
}

const tmpCir: ICircle = { x: 0, y: 0, r: 0 };